package org.kaindorf.kainflix.metadata.controller;

import java.util.List;
import javax.validation.Valid;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kaindorf.kainflix.metadata.exceptions.IllegalDataGivenException;
import org.kaindorf.kainflix.metadata.exceptions.ResourceNotFoundException;
import org.kaindorf.kainflix.metadata.repository.entity.Metadata;
import org.kaindorf.kainflix.metadata.service.MetaDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 *
 * @author Thomas
 */
@Controller
@RequestMapping("/metadata")
public class MetadataController {

    private static final Logger logger = LogManager.getLogger(MetadataController.class);

    @Autowired
    private MetaDataService metaDataService;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    public String showOverview(Model model) {
        Iterable<Metadata> allMetaData = metaDataService.getAllMetaData();
        model.addAttribute("all_metadata", allMetaData);
        return "metadata/show_all_metadata";
    }

    @RequestMapping(value = "product/{productId}", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    public String showForProduct(@PathVariable("productId") Long productId, Model model) {
        List<Metadata> productMetadata = metaDataService.getAllMetaDataWithProductId(productId);
        model.addAttribute("productId", productId);
        model.addAttribute("products_metadata", productMetadata);
        return "metadata/show_metadata_of_product";
    }

    @RequestMapping(value = "{metaDataId}", method = RequestMethod.GET)
    public String showOneDetailed(@PathVariable("metaDataId") long metaDataId, Model model) {
        Metadata metaData = metaDataService.getMetaDataById(metaDataId);
        model.addAttribute("metadata", metaData);
        return "metadata/show_one_metadata";
    }

    // there is no PUT or DELETE specification in HTML5, so the URLs have been extended
    @RequestMapping(value = "create", method = RequestMethod.GET)
    public String showCreateForm(Model model) {
        model.addAttribute("metadata", new Metadata());
        return "metadata/create_metadata";
    }

    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String executeCreate(@Valid Metadata metadata, BindingResult bindingResultMetadata, Model model) {
        if (bindingResultMetadata.hasErrors()) {
            return "metadata/create_metadata";
        }
        try {
            metaDataService.saveMetaData(metadata);
        } catch (IllegalDataGivenException ex) {
            logger.debug("illegal data has been supplied, metadata could not be saved", ex);
            model.addAttribute("metadata", metadata);
            bindingResultMetadata.rejectValue("indentifier", null, "Product with indentifier must be unique.");
            return "metadata/create_metadata";
        }
        return "redirect:/metadata";
    }

    @RequestMapping(value = "edit/{metaDataId}", method = RequestMethod.GET)
    public String showEditForm(@PathVariable("metaDataId") long metaDataId, Model model) {
        Metadata metadata = metaDataService.getMetaDataById(metaDataId);
        model.addAttribute("metadata", metadata);
        return "metadata/edit_metadata";
    }

    @RequestMapping(value = "edit/{metadataId}", method = RequestMethod.POST)
    public String executeEdit(@PathVariable("metadataId") long metadataId, Metadata metadata, BindingResult bindingResultMetadata, Model model) {
        if (metadata.getId() != null) {
            bindingResultMetadata.reject(null, "metadata id in body must be null");
        }
        if (bindingResultMetadata.hasErrors()) { // show form with errors
            metadata.setId(metadataId);
            model.addAttribute("metadata", metadata);
            return "metadata/edit_metadata";
        }
        metadata.setId(metadataId);
        try {
            metaDataService.updateMetaData(metadata);
        } catch (IllegalDataGivenException ex) {
            logger.debug("illegal data has been supplied, metadata could not be updated", ex);
            model.addAttribute("metadata", metadata);
            bindingResultMetadata.rejectValue("indentifier", null, "Product with indentifier must be unique.");
            return "metadata/edit_metadata";
        }
        return "redirect:/metadata";
    }

    @RequestMapping(value = "delete/{metaDataId}", method = RequestMethod.GET)
    public String executeDelete(@PathVariable("metaDataId") long metaDataId) {
        metaDataService.delete(metaDataId);
        return "redirect:/metadata";
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    public String handleResourceNotFoundException(ResourceNotFoundException ex) {
        logger.debug("some non-existing metadata has been requested");
        return "redirect:/metadata";
    }
}
